package com.jic.order.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.jic.common.base.vo.RestResult;
import com.jic.common.redis.RedisClientTemplate;
import com.jic.common.utils.IDUtils;
import com.jic.common.utils.KeyUtils;
import com.jic.market.api.after.MarketApi;
import com.jic.market.api.rest.CouponRestApi;
import com.jic.market.api.rest.GrouponRestApi;
import com.jic.market.request.rest.bargain.MyBargainResponse;
import com.jic.market.request.rest.coupon.QuyerCouponCenterRequest;
import com.jic.market.request.rest.coupon.UseCouponRequest;
import com.jic.market.request.rest.groupon.MyBargainRequest;
import com.jic.market.request.rest.seckill.SeckillInfoRequest;
import com.jic.market.response.rest.SeckillInfoResponse;
import com.jic.market.response.rest.coupon.QueryCouponCenterResponse;
import com.jic.order.api.OrderApi;
import com.jic.order.request.CreateOrderRequest;
import com.jic.order.request.CreateParentOrderRequest;
import com.jic.order.request.FrontParentOrderGoodsRequest;
import com.jic.order.rest.request.*;
import com.jic.order.rest.response.*;
import com.jic.product.after.api.ProductListApi;
import com.jic.product.after.response.ProductAfterInfoByIdResponse;
import com.jic.order.constant.consist.ErrorInfo;
import com.jic.order.constant.consist.RedisKey;
import com.jic.order.constant.consist.SettleConstant;
import com.jic.order.entity.SettleEntity;
import com.jic.order.service.SettleService;
import com.jic.order.service.ShoppingCartService;
import com.jic.product.rest.response.ProductPropertyResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: gaolanyu
 * @date: 2020-02-05
 * @remark: // TODO 异常处理
 */
@Service
@Slf4j
public class SettleServiceImpl implements SettleService {

    @Autowired
    RedisClientTemplate redisClientTemplate;
    @Autowired
    ShoppingCartService shoppingCartService;
    @Resource
    OrderApi orderApi;

    @Autowired
    CouponRestApi couponRestApi;

    @Autowired
    ProductListApi productListApi;

    @Autowired
    private GrouponRestApi grouponRestApi;

    @Resource
    private MarketApi marketApi;

    @Override
    public RestResult<String> initOrder(CartOrderRequest request, boolean directFlag) {
        String userId = shoppingCartService.getUserIdByToken(request.getToken());
        if (!StringUtils.isEmpty(userId)) {
            request.setUserId(Long.parseLong(userId));
        }
        if (!checkSettleEntityKeyExists(request.getUserId())) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "该用户还没有提交结算请求");
        }
        if (checkSettleNum(request.getUserId(), request.getSettleNum())) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "结算虚拟单号不对，请重新提交订单");
        }
        String orderId = invokeOrder(request, directFlag);
        if (StringUtils.isEmpty(orderId)) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "系统繁忙，请重试!");
        }
        orderSuccessExecute(request, directFlag);
        //更新优惠券状态
        if (request.getCouponIds() != null && request.getCouponIds().size() > 0 && org.apache.commons.lang3.StringUtils.isNotEmpty(request.getCouponIds().get(0))) {
            UseCouponRequest couponRequest = new UseCouponRequest();
            couponRequest.setOrderCode(orderId);
            couponRequest.setUserId(userId);
            couponRequest.setCouponCode(request.getCouponIds().get(0));
            RestResult<Boolean> useCouponRes = couponRestApi.useCoupons(couponRequest);
            if ("9999".equals(useCouponRes.getCode())) {
                return RestResult.error("9999", useCouponRes.getMsg());
            }
        }
        return RestResult.success(orderId);
    }

    public void orderSuccessExecute(CartOrderRequest request, boolean directFlag) {
        delGoodsInfo(request, directFlag);
        setCartAmount(request, directFlag);
        delSettleEntity(request);
    }

    public void delSettleEntity(CartOrderRequest request) {
        String settleKey = getSettleKey(request.getUserId());
        redisClientTemplate.del(settleKey);
    }

    public void setCartAmount(CartOrderRequest request, boolean directFlag) {
        log.info("SettleServiceImpl==>setCartAmount==>,userId:{},req:{},directFlag:{}", request.getUserId(), request, directFlag);
        String cartEntityKey = shoppingCartService.getShoppingCartEntityKey(request.getUserId(), directFlag);
        log.info("SettleServiceImpl==>setCartAmount==>,userId:{},cartEntityKey:{},directFlag:{}", request.getUserId(), cartEntityKey, directFlag);
        if (redisClientTemplate.exists(cartEntityKey)) {
            redisClientTemplate.hset(cartEntityKey, RedisKey.saleTotalAmount, "0");
            redisClientTemplate.hset(cartEntityKey, RedisKey.buyTotalAmount, "0");
            redisClientTemplate.hset(cartEntityKey, RedisKey.buyTotalAmount, "0");
        }
    }

    public void delGoodsInfo(CartOrderRequest request, boolean directFlag) {
        String settleKey = getSettleKey(request.getUserId());
        Map<String, String> settleEntity = redisClientTemplate.hgetAll(settleKey);
        String goodsIdStr = settleEntity.get(RedisKey.goodsIdList);
        JSONArray goodsIdJSONArray = JSONArray.parseArray(goodsIdStr);
        List<String> goodsIdList = goodsIdJSONArray.toJavaList(String.class);
        if (CollectionUtils.isEmpty(goodsIdList)) {
            return;
        }
        for (String goodsId : goodsIdList) {
            String goodsKey = shoppingCartService.getShoppingCartGoodsInfoEntityKey(request.getUserId(), goodsId, directFlag);
            log.info("SettleServiceImpl==>delGoodsInfo==>,userId:{},req:{},directFlag:{},goodsKey:{}", request.getUserId(), request, directFlag, goodsKey);
            redisClientTemplate.del(goodsKey);
        }
    }

    public String invokeOrder(CartOrderRequest request, boolean directFlag) {
        CreateParentOrderRequest orderRequest = setCreateParentOrderRequest(request, directFlag);
        if(CollectionUtil.isNotEmpty(request.getCouponIds())){
            if(request.getCouponIds().size()>0){
                orderRequest.setCouponCodeList(request.getCouponIds());
            }
        }
        if (request.getActualPayTotalAmount() != null){
            orderRequest.setActualPayTotalAmount(request.getActualPayTotalAmount());
            orderRequest.setSaleTotalAmount(request.getSaleTotalAmount());
            orderRequest.setDiscountTotalAmount(request.getDiscountTotalAmount());
            orderRequest.setBuyTotalAmount(request.getActualPayTotalAmount());
        }
        orderRequest.setProductType(request.getProductType());
        orderRequest.setVirtualPhone(request.getVirtualPhone());
        log.info("SettleServiceImpl==>invokeOrder==>,userId:{},req:{},directFlag:{}", request.getUserId(), orderRequest, directFlag);
        RestResult<String> orderResponse = orderApi.create(orderRequest);
        log.info("SettleServiceImpl==>invokeOrder==>,userId:{},resp:{},directFlag:{}", request.getUserId(), orderResponse, directFlag);
        //TODO 调用订单系统生成订单
//        return IDUtils.GenerateBillNo("order");
        return orderResponse.getData();
    }

    public CreateParentOrderRequest setCreateParentOrderRequest(CartOrderRequest request, boolean directFlag) {
        List<String> couponIds = request.getCouponIds();
        BigDecimal couponAmount = BigDecimal.ZERO;
        if(CollectionUtil.isNotEmpty(couponIds)){
            QuyerCouponCenterRequest centerRequest = new QuyerCouponCenterRequest();
            centerRequest.setCouponCode(couponIds.get(0));
            RestResult<QueryCouponCenterResponse> result = couponRestApi.queryCouponInfo(centerRequest);
            if(!result.getCode().equals("9999")){
                couponAmount = result.getData().getCouponAmount();
            }
        }
        CreateParentOrderRequest orderRequest = new CreateParentOrderRequest();
        orderRequest.setSerialNo(request.getSettleNum());
        orderRequest.setSaleChannel(SettleConstant.saleChannel.bbc);
        orderRequest.setBuyerId(request.getUserId());
        orderRequest.setBuyerUsername("");

        String settleKey = getSettleKey(request.getUserId());
        Map<String, String> result = redisClientTemplate.hgetAll(settleKey);

        if(org.apache.commons.lang.StringUtils.isNotEmpty(result.get(RedisKey.receiverName))){
            orderRequest.setReceiverProvinceId(Long.parseLong(result.get(RedisKey.receiverProvinceId)));
            orderRequest.setReceiverProvinceName(result.get(RedisKey.receiverProvinceName));
            orderRequest.setReceiverCityId(Long.parseLong(result.get(RedisKey.receiverCityId)));
            orderRequest.setReceiverCityName(result.get(RedisKey.receiverCityName));
            orderRequest.setReceiverCountryId(Long.parseLong(result.get(RedisKey.receiverCountryId)));
            orderRequest.setReceiverRegionName(result.get(RedisKey.receiverRegionName));
            orderRequest.setReceiverName(result.get(RedisKey.receiverName));
            orderRequest.setReceiverPhone(result.get(RedisKey.receiverPhone));
            orderRequest.setReceiverAddress(result.get(RedisKey.receiverAddress));
        }else{
            orderRequest.setReceiverProvinceId(request.getReceiverProvinceId());
            orderRequest.setReceiverProvinceName(request.getReceiverProvinceName());
            orderRequest.setReceiverCityId(request.getReceiverCityId());
            orderRequest.setReceiverCityName(request.getReceiverCityName());
            orderRequest.setReceiverCountryId(request.getReceiverCountryId());
            orderRequest.setReceiverRegionName(request.getReceiverRegionName());
            orderRequest.setReceiverName(request.getReceiverName());
            orderRequest.setReceiverPhone(request.getReceiverPhone());
            orderRequest.setReceiverAddress(request.getReceiverAddress());
        }

        orderRequest.setSaleTotalAmount(new BigDecimal(result.get(RedisKey.saleTotalAmount)));
        //优惠券金额
//        orderRequest.setDiscountTotalAmount(new BigDecimal(result.get(RedisKey.discountTotalAmount))
//                .add(new BigDecimal(result.get(RedisKey.couponTotalAmount))));
        orderRequest.setDiscountTotalAmount(couponAmount);

        orderRequest.setBuyTotalAmount(new BigDecimal(result.get(RedisKey.buyTotalAmount)));
        orderRequest.setExpressTotalFee(new BigDecimal(result.get(RedisKey.logisticsAmount)));
        orderRequest.setInvoiceId(request.getInvoiceId());
        //减去优惠券金额
        orderRequest.setActualPayTotalAmount(orderRequest.getBuyTotalAmount().add(orderRequest.getExpressTotalFee()).subtract(couponAmount));
        String goodsIdStr = result.get(RedisKey.goodsIdList);
        JSONArray goodsArray = JSONArray.parseArray(goodsIdStr);
        List<String> goodsIdList = goodsArray.toJavaList(String.class);
        orderRequest.setCreateOrderRequestList(setCreateOrderRequestList(goodsIdList, request, directFlag, orderRequest));
        return orderRequest;
    }

    public List<CreateOrderRequest> setCreateOrderRequestList(List<String> goodsIdList, CartOrderRequest request, boolean directFlag, CreateParentOrderRequest createParentOrderRequest) {
        List<ShoppingCartSubInfo> subInfos = getShoppingCartSubInfoList(goodsIdList, request.getUserId(), directFlag);
        if (CollectionUtils.isEmpty(subInfos)) {
            return new ArrayList<>();
        }
        BigDecimal expressFee = createParentOrderRequest.getExpressTotalFee();
        int subInfoNum = subInfos.size();
        BigDecimal subInfoExpressFee = expressFee.divide(new BigDecimal(subInfoNum));
        List<CreateOrderRequest> orderRequestList = new ArrayList<>();
        for (ShoppingCartSubInfo subInfo : subInfos) {
            CreateOrderRequest orderRequest = new CreateOrderRequest();
            orderRequest.setMerchantId(subInfo.getMerchantId());
            orderRequest.setMerchantName(subInfo.getMerchantName());
            orderRequest.setStoreId(subInfo.getStoreId());
            orderRequest.setStoreName(subInfo.getStoreName());
            orderRequest.setStoreLogoUrl(subInfo.getStoreLogoUrl());

            BigDecimal saleTotalAmount = BigDecimal.ZERO;
            BigDecimal discountTotalAmount = BigDecimal.ZERO;
            BigDecimal buyTotalAmount = BigDecimal.ZERO;
            BigDecimal expressTotalFee = BigDecimal.ZERO;
            BigDecimal actualPayTotalAmount = BigDecimal.ZERO;
            List<FrontParentOrderGoodsRequest> goodsList = new ArrayList<>();
            int goodsSize = subInfo.getShoppingCartGoodsInfoList().size();
            for (ShoppingCartGoodsInfo goodsInfo : subInfo.getShoppingCartGoodsInfoList()) {
                FrontParentOrderGoodsRequest goodsRequest = new FrontParentOrderGoodsRequest();
                goodsRequest.setBuyUnitPrice(goodsInfo.getBuyUnitPrice());
                goodsRequest.setDiscountUnitPrice(goodsInfo.getDiscountUnitPrice());
                goodsRequest.setExpressUnitFee(BigDecimal.ONE);
                goodsRequest.setGoodsId(Long.parseLong(goodsInfo.getGoodsId()));
                goodsRequest.setGoodsImgUrl(goodsInfo.getGoodsUrl());
                goodsRequest.setGoodsName(goodsInfo.getGoodsName());
                goodsRequest.setGoodsNum(goodsInfo.getGoodsNum());
                goodsRequest.setGoodsType(1);
                goodsRequest.setMerchantId(subInfo.getMerchantId());
                goodsRequest.setMerchantName(subInfo.getMerchantName());
                goodsRequest.setSaleUnitPrice(goodsInfo.getSaleUnitPrice());
                goodsRequest.setStoreId(subInfo.getStoreId());
                goodsRequest.setStoreLogoUrl(subInfo.getStoreLogoUrl());
                goodsRequest.setStoreName(subInfo.getStoreName());
                goodsRequest.setPromotionId(goodsInfo.getPromotionId());
                goodsRequest.setPromotionType(goodsInfo.getPromotionType());
                goodsRequest.setGroupType(goodsInfo.getGroupType());
                goodsRequest.setDistributorId(request.getDistributorId());
                BigDecimal actualUnitAmont = goodsInfo.getBuyUnitPrice().add(goodsRequest.getExpressUnitFee());
                goodsRequest.setActualPayTotalAmount(actualUnitAmont.multiply(new BigDecimal(goodsRequest.getGoodsNum())));
                goodsList.add(goodsRequest);
                saleTotalAmount = saleTotalAmount.add(goodsRequest.getSaleUnitPrice().multiply(new BigDecimal(goodsRequest.getGoodsNum())));
                discountTotalAmount = discountTotalAmount.add(goodsRequest.getDiscountUnitPrice().multiply(new BigDecimal(goodsRequest.getGoodsNum())));
                buyTotalAmount = buyTotalAmount.add(goodsRequest.getBuyUnitPrice().multiply(new BigDecimal(goodsRequest.getGoodsNum())));
                expressTotalFee = expressTotalFee.add(goodsRequest.getExpressUnitFee().multiply(new BigDecimal(goodsRequest.getGoodsNum())));
                actualPayTotalAmount = actualPayTotalAmount.add(goodsRequest.getActualPayTotalAmount());
            }

            orderRequest.setSaleTotalAmount(saleTotalAmount);
            orderRequest.setDiscountTotalAmount(discountTotalAmount);
            orderRequest.setBuyTotalAmount(buyTotalAmount);
            orderRequest.setExpressTotalFee(expressTotalFee);
            orderRequest.setActualPayTotalAmount(actualPayTotalAmount);
            orderRequest.setGoodsList(goodsList);
            orderRequestList.add(orderRequest);
        }
        return orderRequestList;
    }

    public boolean checkSettleNum(long userId, String settleNum) {
        String settleKey = getSettleKey(userId);
        String settelNum = redisClientTemplate.hget(settleKey, RedisKey.settelNum);
        if (settleNum.equals(settelNum)) {
            return true;
        }
        return false;
    }

    @Override
    public RestResult<CartSettleResponse> settle(CartSettleRequest request, boolean directFlag) {
        if (!checkShoppingCartEntityKeyExists(request.getUserId(), directFlag)) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "没有找到该用户购物车信息");
        }
        List<String> goodIds = new ArrayList<String>();
        ShoppingCartInfoListQueryRequest request1 = new ShoppingCartInfoListQueryRequest();
        request1.setToken(request.getToken());
        request1.setUserId(request.getUserId());
        RestResult<ShoppingCartInfoListQueryResponse> cart = shoppingCartService.queryShoppingCart(request1, directFlag);
        if (cart.getCode().equals("0000")) {
            List<ShoppingCartSubInfo> cartSubInfoList = cart.getData().getShoppingCartSubInfoList();
            if (CollectionUtil.isNotEmpty(cartSubInfoList)) {
                for (ShoppingCartSubInfo cartSubInfo : cartSubInfoList) {
                    List<ShoppingCartGoodsInfo> goodsInfoList = cartSubInfo.getShoppingCartGoodsInfoList();
                    if (CollectionUtil.isNotEmpty(goodsInfoList)) {
                        for (ShoppingCartGoodsInfo shoppingCartGoodsInfo : goodsInfoList) {
                            String goodsId = shoppingCartGoodsInfo.getGoodsId();
                            Integer goodsNum = shoppingCartGoodsInfo.getGoodsNum();
                            Boolean stock = productListApi.queryProductStock(goodsId, goodsNum);
                            if (!stock) {
                                goodIds.add(goodsId);
                                //没有库存的商品需要清除购物车
                                ShoppingCartDeleteRequest deleteRequest = new ShoppingCartDeleteRequest();
                                ArrayList<ShoppingCartDeleteSubRequest> shoppingCartDeleteSubRequests = new ArrayList<>();
                                ShoppingCartDeleteSubRequest shoppingCartDeleteSubRequest = new ShoppingCartDeleteSubRequest();
                                shoppingCartDeleteSubRequest.setShoppingCardChildrenId(cartSubInfo.getShoppingCartChildrenId());
                                ArrayList<String> goodsIdList = new ArrayList<>();
                                goodsIdList.add(goodsId);
                                shoppingCartDeleteSubRequest.setGoodsIdList(goodsIdList);
                                deleteRequest.setShoppingCartDeleteSubRequests(shoppingCartDeleteSubRequests);
                                shoppingCartService.deleteGoodsInfo(deleteRequest, directFlag);
                            }
                        }
                    }
                }
            }
        }

        if (checkSettleEntityKeyExists(request.getUserId())) {
            String settelEntityKey = getSettleKey(request.getUserId());
            redisClientTemplate.del(settelEntityKey);
        }
        SettleEntity settleEntity = setSettleEntity(request, directFlag);
        shoppingCartService.saveNewEntityToRedis(settleEntity, getSettleKey(request.getUserId()));

        CartSettleResponse response = setCartSettleResponse(request, settleEntity, directFlag);

        response.setGoodIds(goodIds);


        return RestResult.success(response);
    }

    @Override
    public RestResult<CartSettleAddressResponse> address(CartSettleAddressRequest cartSettleAddressRequest, boolean directFlag) {
        if (!checkSettleEntityKeyExists(cartSettleAddressRequest.getUserId())) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "请先提交订单!");
        }
        if (checkSettleNum(cartSettleAddressRequest.getUserId(), cartSettleAddressRequest.getSettleNum())) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "结算虚拟单号不对，请重新提交订单");
        }
        CartSettleAddressResponse response = setSettleEntity(cartSettleAddressRequest, directFlag);
        return RestResult.success(response);
    }

    @Override
    public RestResult<CartSettleResponse> directSettle(DirectSettleRequest directSettleRequest) {
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(directSettleRequest.getPromotionId()) && directSettleRequest.getPromotionType().toString().equals("11")) {
            SeckillInfoRequest seckillInfoRequest = new SeckillInfoRequest();
            seckillInfoRequest.setGoodsId(Long.valueOf(directSettleRequest.getGoodsId()));
            seckillInfoRequest.setPromotionId(Long.valueOf(directSettleRequest.getPromotionId()));
            RestResult<SeckillInfoResponse> seckillInfoResponseRestResult = marketApi.getSecondsKillInfo(seckillInfoRequest);
            directSettleRequest.setSaleUnitPrice(seckillInfoResponseRestResult.getData().getPromPrice());
        }

        RestResult<ProductAfterInfoByIdResponse> responseRestResult =
                productListApi.queryProductInfoById(Long.valueOf(directSettleRequest.getGoodsId()));
        if (null != responseRestResult && null != responseRestResult.getData()) {
            directSettleRequest.setGoodsName(responseRestResult.getData().getChineseName());
            directSettleRequest.setGoodsUrl(responseRestResult.getData().getPictureUrl());
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(directSettleRequest.getPromotionId()) && directSettleRequest.getPromotionType().toString().equals("11")) {

            }else if(org.apache.commons.lang3.StringUtils.isNotEmpty(directSettleRequest.getPromotionId()) && directSettleRequest.getPromotionType().toString().equals("20")){
                directSettleRequest.setSaleUnitPrice(directSettleRequest.getSaleUnitPrice());
            } else {
                directSettleRequest.setSaleUnitPrice(responseRestResult.getData().getSalePriceWithTax());
            }
        }
        if (checkSettleEntityKeyExists(directSettleRequest.getUserId())) {
            CartOrderRequest request = new CartOrderRequest();
            request.setUserId(directSettleRequest.getUserId());
            orderSuccessExecute(request, true);
        }
        RestResult<ShoppingCartAddResponse> addRestResponse = shoppingCartService.add(setShoppingCartAddRequest(directSettleRequest), true);
        if (!RestResult.checkIsSuccess(addRestResponse)) {
            return RestResult.error(addRestResponse.getCode(), addRestResponse.getMsg());
        }
        String shoppingCartId = addRestResponse.getData().getShoppingCardId();
        RestResult<Boolean> selectResponse = shoppingCartService.selected(setShoppingCartSelectedRequest(directSettleRequest, shoppingCartId), true);
        if (!RestResult.checkIsSuccess(selectResponse)) {
            return RestResult.error(selectResponse.getCode(), selectResponse.getMsg());
        }

        RestResult<CartSettleResponse> settleResponse = settle(setSettleRequest(directSettleRequest, shoppingCartId), true);
        if (!RestResult.checkIsSuccess(selectResponse)) {
            return RestResult.error(settleResponse.getCode(), settleResponse.getMsg());
        }

        if(null!=directSettleRequest){
            RestResult<List<ProductPropertyResponse>> listRestResult = productListApi.queryProductPropetyBySpuId(Long.valueOf(directSettleRequest.getGoodsId()));
            if (null != listRestResult && null != listRestResult.getData()) {
                settleResponse.getData().setProductPropertyResponses(listRestResult.getData());
            }
        }
        return settleResponse;
    }

    @Override
    public RestResult<CartSettleResponse> grouponSettle(DirectSettleRequest directSettleRequest) {
        if (directSettleRequest.getBargainId() == null) {
            return RestResult.error("9999", "砍价活动id不能为空");
        }
        RestResult<ProductAfterInfoByIdResponse> responseRestResult =
                productListApi.queryProductInfoById(Long.valueOf(directSettleRequest.getGoodsId()));

        RestResult<List<MyBargainResponse>> result = grouponRestApi.launchGrouponProductDetail(new MyBargainRequest() {{
            setBargainId(directSettleRequest.getBargainId());
        }});
        if (null == result || CollectionUtils.isEmpty(result.getData())) {
            return RestResult.error("9999", "没有查询到对应的砍价活动商品");
        }
        if (null == responseRestResult || null == responseRestResult.getData()) {
            return RestResult.error("9999", "商品不存在");
        } else {
            MyBargainResponse bargainResponse = result.getData().get(0);
            if (bargainResponse.getBuyPrice().equals(BigDecimal.ZERO) || bargainResponse.getBuyPrice().compareTo(BigDecimal.ZERO) == -1) {
                return RestResult.error("9999", "商品最终价格不能为空或小于0");
            }
            directSettleRequest.setGoodsName(responseRestResult.getData().getChineseName());
            directSettleRequest.setGoodsUrl(responseRestResult.getData().getPictureUrl());
            directSettleRequest.setSaleUnitPrice(result.getData().get(0).getBuyPrice());
        }
        if (checkSettleEntityKeyExists(directSettleRequest.getUserId())) {
            CartOrderRequest request = new CartOrderRequest();
            request.setUserId(directSettleRequest.getUserId());
            orderSuccessExecute(request, true);
        }
        RestResult<ShoppingCartAddResponse> addRestResponse = shoppingCartService.add(setShoppingCartAddRequest(directSettleRequest), true);
        if (!RestResult.checkIsSuccess(addRestResponse)) {
            return RestResult.error(addRestResponse.getCode(), addRestResponse.getMsg());
        }
        String shoppingCartId = addRestResponse.getData().getShoppingCardId();
        RestResult<Boolean> selectResponse = shoppingCartService.selected(setShoppingCartSelectedRequest(directSettleRequest, shoppingCartId), true);
        if (!RestResult.checkIsSuccess(selectResponse)) {
            return RestResult.error(selectResponse.getCode(), selectResponse.getMsg());
        }

        RestResult<CartSettleResponse> settleResponse = settle(setSettleRequest(directSettleRequest, shoppingCartId), true);
        if (!RestResult.checkIsSuccess(selectResponse)) {
            return RestResult.error(settleResponse.getCode(), settleResponse.getMsg());
        }
        return settleResponse;
    }

    @Override
    public RestResult<Boolean> getDirectFlagByShoppingCartId(String shoppingCartId, long userId) {
        if (org.apache.commons.lang.StringUtils.isBlank(shoppingCartId)) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "shoppingCartId不能为空");
        }
        if (!checkShoppingCartEntityKeyExists(userId, false) && !checkShoppingCartEntityKeyExists(userId, true)) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "该用户没有购物车信息");
        }
        String cartKey = shoppingCartService.getShoppingCartEntityKey(userId, false);
        String cartId = redisClientTemplate.hget(cartKey, RedisKey.shoppingCartId);

        String directKey = shoppingCartService.getShoppingCartEntityKey(userId, true);
        String directCartId = redisClientTemplate.hget(directKey, RedisKey.shoppingCartId);

        if (org.apache.commons.lang.StringUtils.equals(cartId, directCartId) && org.apache.commons.lang.StringUtils.isNotBlank(cartId)) {
            return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "系统异常，单号重复");
        }

        if (shoppingCartId.equals(cartId)) {
            return RestResult.success(false);
        }
        if (shoppingCartId.equals(directCartId)) {
            return RestResult.success(true);
        }
        return RestResult.error(ErrorInfo.SYSTEM_ERROR_CODE, "shoppingCartId不可用");
    }


    public CartSettleRequest setSettleRequest(DirectSettleRequest directSettleRequest, String shoppingCartId) {
        CartSettleRequest settleRequest = new CartSettleRequest();
        settleRequest.setShoppingCartId(shoppingCartId);
        settleRequest.setUserId(directSettleRequest.getUserId());
        return settleRequest;
    }

    public ShoppingCartSelectedRequest setShoppingCartSelectedRequest(DirectSettleRequest directSettleRequest, String shoppingCartId) {
        ShoppingCartSelectedRequest request = new ShoppingCartSelectedRequest();
        List<String> goodsIdList = new ArrayList<>();
        goodsIdList.add(directSettleRequest.getGoodsId());
        request.setGoodsIdList(goodsIdList);
        request.setShoppingCartId(shoppingCartId);
        request.setUserId(directSettleRequest.getUserId());
        return request;
    }

    public ShoppingCartAddRequest setShoppingCartAddRequest(DirectSettleRequest directSettleRequest) {
        ShoppingCartAddRequest request = new ShoppingCartAddRequest();
        request.setGoodsId(directSettleRequest.getGoodsId());
        request.setGoodsName(directSettleRequest.getGoodsName());
        request.setGoodsNum(directSettleRequest.getGoodsNum());
        request.setGoodsUrl(directSettleRequest.getGoodsUrl());
        request.setSaleUnitPrice(directSettleRequest.getSaleUnitPrice());
        request.setSelected(false);
        request.setUserId(directSettleRequest.getUserId());
        request.setPromotionId(directSettleRequest.getPromotionId());
        request.setPromotionType(directSettleRequest.getPromotionType());
        request.setGroupType(directSettleRequest.getGroupType());
        return request;
    }


    public CartSettleAddressResponse setSettleEntity(CartSettleAddressRequest request, boolean directFlag) {
        CartSettleAddressResponse response = new CartSettleAddressResponse();
        response.setLogisticsAmount(getLogisticsAmount(request, directFlag));
        response.setSettleNum(request.getSettleNum());
        response.setShoppingCartId(request.getShoppingCartId());
        response.setUserId(request.getUserId());

        String settleKey = getSettleKey(request.getUserId());
        log.info("SettleController==>address==>,userId:{},settleKey:{}", request.getUserId(), settleKey);
        String buyTotalAmount = redisClientTemplate.hget(settleKey, RedisKey.buyTotalAmount);
//        BigDecimal buyTotalAmountDec = new BigDecimal(buyTotalAmount).add(response.getLogisticsAmount());
        BigDecimal buyTotalAmountDec = new BigDecimal(buyTotalAmount);
        Map<String, String> param = new HashMap<>();
        param.put(RedisKey.logisticsAmount, response.getLogisticsAmount().toString());
        param.put(RedisKey.buyTotalAmount, buyTotalAmountDec.toString());
        param.put(RedisKey.receiverProvinceId, Long.toString(request.getReceiverProvinceId()));
        param.put(RedisKey.receiverProvinceName, request.getReceiverProvinceName());
        param.put(RedisKey.receiverCityId, Long.toString(request.getReceiverCityId()));
        param.put(RedisKey.receiverCityName, request.getReceiverCityName());
        param.put(RedisKey.receiverCountryId, Long.toString(request.getReceiverCityId()));
        param.put(RedisKey.receiverRegionName, request.getReceiverRegionName());
        param.put(RedisKey.receiverName, request.getReceiverName());
        param.put(RedisKey.receiverPhone, request.getReceiverPhone());
        param.put(RedisKey.receiverAddress, request.getReceiverAddress());

        redisClientTemplate.hmset(settleKey, param);
        return response;
    }

    public BigDecimal getLogisticsAmount(CartSettleAddressRequest request, boolean directFlag) {
        String settleKey = getSettleKey(request.getUserId());
        String goodsIdStr = redisClientTemplate.hget(settleKey, RedisKey.goodsIdList);
        JSONArray goodsArray = JSONArray.parseArray(goodsIdStr);
        List<String> goodsIdList = goodsArray.toJavaList(String.class);
        if (CollectionUtils.isEmpty(goodsIdList)) {
            return BigDecimal.ZERO;
        }
        int goodsNum = 0;
        for (String goodsId : goodsIdList) {
            String goodEntityKey = shoppingCartService.getShoppingCartGoodsInfoEntityKey(request.getUserId(), goodsId, directFlag);
            if (!redisClientTemplate.exists(goodEntityKey)) {
                continue;
            }
            String goodsNumStr = redisClientTemplate.hget(goodEntityKey, RedisKey.goodsNum);
            int goodsNumInt = Integer.parseInt(goodsNumStr);
            goodsNum = goodsNum + goodsNumInt;
        }
        //TODO 先根据商品数量计算运费
        return BigDecimal.ZERO;
    }

    public CartSettleResponse setCartSettleResponse(CartSettleRequest request, SettleEntity settleEntity, boolean directFlag) {
        CartSettleResponse response = new CartSettleResponse();
        response.setLogisticsAmount(settleEntity.getLogisticsAmount());
        response.setDiscountTotalAmount(settleEntity.getDiscountTotalAmount());
        response.setCouponTotalAmount(settleEntity.getCouponTotalAmount());
        response.setBuyTotalAmount(settleEntity.getBuyTotalAmount());
        response.setReceiverAddress(settleEntity.getReceiverAddress());
        response.setReceiverCityId(settleEntity.getReceiverCityId());
        response.setReceiverCityName(settleEntity.getReceiverCityName());
        response.setReceiverCountryId(settleEntity.getReceiverCountryId());
        response.setReceiverName(settleEntity.getReceiverName());
        response.setReceiverPhone(settleEntity.getReceiverPhone());
        response.setReceiverProvinceId(settleEntity.getReceiverProvinceId());
        response.setReceiverProvinceName(settleEntity.getReceiverProvinceName());
        response.setReceiverRegionName(settleEntity.getReceiverRegionName());
        response.setSaleTotalAmount(settleEntity.getSaleTotalAmount());
        response.setSettleNum(settleEntity.getSettleNum());
        response.setShoppingCartId(settleEntity.getShoppingCartId());
        response.setUserId(request.getUserId());

        List<ShoppingCartSubInfo> subInfos = getShoppingCartSubInfoList(settleEntity.getGoodsIdList(), request.getUserId(), directFlag);
        response.setShoppingCartSubInfoList(subInfos);
        return response;
    }

    public List<ShoppingCartSubInfo> getShoppingCartSubInfoList(List<String> goodsIdList, long userId, boolean directFlag) {
        if (CollectionUtils.isEmpty(goodsIdList)) {
            return new ArrayList<ShoppingCartSubInfo>();
        }
        List<ShoppingCartSubInfo> subInfos = new ArrayList<>();
        Map<String, List<String>> subInfosMap = groupGoodsIdList(goodsIdList);
        for (String childrenId : subInfosMap.keySet()) {
            ShoppingCartSubInfo shoppingCartSubInfo = getShoppingCartGoodsInfoList(subInfosMap.get(childrenId), userId, directFlag, childrenId);
            subInfos.add(shoppingCartSubInfo);
        }
        return subInfos;
    }

    public ShoppingCartSubInfo getShoppingCartGoodsInfoList(List<String> goodsIdList, long userId, boolean directFlag, String childrenId) {
        ShoppingCartSubInfo shoppingCartSubInfo = new ShoppingCartSubInfo();
        shoppingCartSubInfo.setShoppingCartChildrenId(childrenId);

        String subKey = shoppingCartService.getShoppingCartSubInfoEntityKey(userId, childrenId, directFlag);
        Map<String, String> subEntity = redisClientTemplate.hgetAll(subKey);

        shoppingCartSubInfo.setMerchantId(Long.parseLong(subEntity.get(RedisKey.merchantId)));
        shoppingCartSubInfo.setMerchantName(subEntity.get(RedisKey.merchantName));
        shoppingCartSubInfo.setStoreId(Long.parseLong(subEntity.get(RedisKey.storeId)));
        shoppingCartSubInfo.setStoreName(subEntity.get(RedisKey.storeName));
        shoppingCartSubInfo.setStoreLogoUrl(subEntity.get(RedisKey.storeLogoUrl));

        List<ShoppingCartGoodsInfo> goodsInfoList = new ArrayList<>();
        BigDecimal subBuyTotalAmount = BigDecimal.ZERO;
        for (String goodsId : goodsIdList) {
            String goodsKey = shoppingCartService.getShoppingCartGoodsInfoEntityKey(userId, goodsId, directFlag);
            if (!redisClientTemplate.exists(goodsKey)) {
                continue;
            }
            Map<String, String> goodsInfo = redisClientTemplate.hgetAll(goodsKey);

            ShoppingCartGoodsInfo shoppingCartGoodsInfo = new ShoppingCartGoodsInfo();
            shoppingCartGoodsInfo.setSelected(shoppingCartService.getSelectedStatus(goodsInfo.get(RedisKey.selected)));
            shoppingCartGoodsInfo.setSaleUnitPrice(new BigDecimal(goodsInfo.get(RedisKey.saleUnitPrice)));
            shoppingCartGoodsInfo.setGoodsNum(Integer.parseInt(goodsInfo.get(RedisKey.goodsNum)));
//            shoppingCartGoodsInfo.setGoodsName(goodsInfo.get(RedisKey.goodsName));
//            shoppingCartGoodsInfo.setGoodsUrl(goodsInfo.get(RedisKey.goodsUrl));
            RestResult<ProductAfterInfoByIdResponse> responseRestResult =
                    productListApi.queryProductInfoById(Long.valueOf(goodsId));
            if (null != responseRestResult && null != responseRestResult.getData()) {
                shoppingCartGoodsInfo.setGoodsName(responseRestResult.getData().getChineseName());
                shoppingCartGoodsInfo.setGoodsUrl(responseRestResult.getData().getPictureUrl());
                shoppingCartSubInfo.setDeptId(responseRestResult.getData().getDeptId());
                shoppingCartGoodsInfo.setSaleUnitPrice(responseRestResult.getData().getSalePriceWithTax());
            }
            shoppingCartGoodsInfo.setGoodsId(goodsId);
            shoppingCartGoodsInfo.setDiscountUnitPrice(new BigDecimal(goodsInfo.get(RedisKey.discountUnitPrice)));
            shoppingCartGoodsInfo.setCouponId(new ArrayList<>());
            shoppingCartGoodsInfo.setCouponAmount(BigDecimal.ZERO);
            shoppingCartGoodsInfo.setBuyUnitPrice(new BigDecimal(goodsInfo.get(RedisKey.buyUnitPrice)));
            shoppingCartGoodsInfo.setPromotionType(goodsInfo.get(RedisKey.promotionType) == null ? null :
                    Integer.parseInt(goodsInfo.get(RedisKey.promotionType)));
            shoppingCartGoodsInfo.setPromotionId(goodsInfo.get(RedisKey.promotionId));
            shoppingCartGoodsInfo.setGroupType(goodsInfo.get(RedisKey.groupType) == null ? null :
                    Integer.parseInt(goodsInfo.get(RedisKey.groupType)));
            goodsInfoList.add(shoppingCartGoodsInfo);
            subBuyTotalAmount = subBuyTotalAmount.add(shoppingCartGoodsInfo.getBuyUnitPrice()
                    .multiply(new BigDecimal(shoppingCartGoodsInfo.getGoodsNum())));
        }

        shoppingCartSubInfo.setSubBuyTotalAmount(subBuyTotalAmount);
        shoppingCartSubInfo.setShoppingCartGoodsInfoList(goodsInfoList);
        return shoppingCartSubInfo;
    }

    public Map<String, List<String>> groupGoodsIdList(List<String> goodsIdList) {
        Map<String, List<String>> subInfosMap = new HashMap<>();
        for (String goodsId : goodsIdList) {
            String childrenId = shoppingCartService.getShoppingCartSubId(goodsId).getShoppingCartChildrenId();
            if (!subInfosMap.containsKey(childrenId)) {
                List<String> goodsList = new ArrayList<>();
                goodsList.add(goodsId);
                subInfosMap.put(childrenId, goodsList);
            } else {
                List<String> goodsList = subInfosMap.get(childrenId);
                goodsList.add(goodsId);
                subInfosMap.put(childrenId, goodsList);
            }
        }
        return subInfosMap;
    }

    public SettleEntity setSettleEntity(CartSettleRequest request, boolean directFlag) {
        Map<String, String> cartInfo = getCartInfo(request, directFlag);

        SettleEntity settleEntity = new SettleEntity();
        settleEntity.setBuyTotalAmount(new BigDecimal(cartInfo.get(RedisKey.buyTotalAmount)));
        settleEntity.setCouponTotalAmount(BigDecimal.ZERO);
        settleEntity.setDiscountTotalAmount(BigDecimal.ZERO);
        settleEntity.setLogisticsAmount(BigDecimal.ZERO);
        settleEntity.setReceiverAddress("");
        settleEntity.setReceiverCityId(0);
        settleEntity.setReceiverCityName("");
        settleEntity.setReceiverCountryId(0);
        settleEntity.setReceiverName("");
        settleEntity.setReceiverPhone("");
        settleEntity.setReceiverProvinceId(0);
        settleEntity.setReceiverProvinceName("");
        settleEntity.setReceiverRegionName("");
        settleEntity.setSaleTotalAmount(new BigDecimal(cartInfo.get(RedisKey.saleTotalAmount)));
        settleEntity.setSettleNum(IDUtils.GenerateBillNo());
        settleEntity.setShoppingCartId(cartInfo.get(RedisKey.shoppingCartId));

        List<String> goodsIdList = getSettleGoodsIdList(request, directFlag);
        settleEntity.setGoodsIdList(goodsIdList);
        return settleEntity;
    }

    public List<String> getSettleGoodsIdList(CartSettleRequest request, boolean directFlag) {
        String cartKey = shoppingCartService.getShoppingCartEntityKey(request.getUserId(), directFlag);
        String shoppingCartSubInfoListKey = redisClientTemplate.hget(cartKey, RedisKey.shoppingCartSubInfoListKey);
        if (StringUtils.isEmpty(shoppingCartSubInfoListKey)) {
            return new ArrayList<>();
        }
        String[] subInfosList = shoppingCartSubInfoListKey.split("\\|");
        List<String> goodsIdList = new ArrayList<>();
        for (String subInfoKey : subInfosList) {
            String subKey = shoppingCartService.getShoppingCartSubInfoEntityKey(request.getUserId(), subInfoKey, directFlag);
            String goodsIdKeyStr = redisClientTemplate.hget(subKey, RedisKey.shoppingCartGoodsInfoListKey);
            if (StringUtils.isEmpty(goodsIdKeyStr)) {
                continue;
            }
            String[] goodsIdKey = goodsIdKeyStr.split("\\|");
            for (String goodsId : goodsIdKey) {
                String goodsKey = shoppingCartService.getShoppingCartGoodsInfoEntityKey(request.getUserId(), goodsId, directFlag);
                if (!redisClientTemplate.exists(goodsKey)) {
                    continue;
                }
                String selected = redisClientTemplate.hget(goodsKey, RedisKey.selected);
                if (shoppingCartService.getSelectedStatus(selected)) {
                    goodsIdList.add(goodsId);
                }
            }
        }
        return goodsIdList;
    }


    public boolean checkSettleEntityKeyExists(long userId) {
        String settleKey = getSettleKey(userId);
        return redisClientTemplate.exists(settleKey);
    }

    public String getSettleKey(long userId) {
        HashMap<String, String> param = new HashMap<>(2);
        param.put(RedisKey.userId, Long.toString(userId));
        String settleKey = KeyUtils.replaceKey(RedisKey.SettleEntityKey, param);
        return settleKey;
    }


    public Map<String, String> getCartInfo(CartSettleRequest request, boolean directFlag) {
        String cartEntityKey = shoppingCartService.getShoppingCartEntityKey(request.getUserId(), directFlag);
        Map<String, String> cartResult = redisClientTemplate.hgetAll(cartEntityKey);
        return cartResult;
    }


    public Boolean checkShoppingCartEntityKeyExists(long userId, boolean directFlag) {
        String shoppingCartEntityKey = shoppingCartService.getShoppingCartEntityKey(userId, directFlag);
        return redisClientTemplate.exists(shoppingCartEntityKey);
    }
}
